/*
 *
 *  * Copyright 2023  腾羚智能, Inc. All rights reserved.
 *
 */

package cn.wuxing.mediation.businessplatform.service.impl;

import static cn.wuxing.mediation.common.utils.PageUtils.startPage;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import cn.wuxing.mediation.businessplatform.domain.annotation.BusinessTag;
import cn.wuxing.mediation.businessplatform.domain.dto.BaseBusinessListDTO;
import cn.wuxing.mediation.businessplatform.domain.enums.EventStateEnum;
import cn.wuxing.mediation.businessplatform.domain.enums.OperatingTypeEnum;
import cn.wuxing.mediation.businessplatform.domain.vo.ApplicantHistoryListVO;
import cn.wuxing.mediation.businessplatform.domain.vo.BaseBusinessListVO;
import cn.wuxing.mediation.businessplatform.domain.vo.ChangeWindowDetailVO;
import cn.wuxing.mediation.businessplatform.domain.vo.HanderTypeRecordVO;
import cn.wuxing.mediation.businessplatform.factory.BusinessFactory;
import cn.wuxing.mediation.businessplatform.mapper.business.BaseBusinessListMapper;
import cn.wuxing.mediation.businessplatform.mapper.business.CmOperatingRecordMapper;
import cn.wuxing.mediation.businessplatform.mapper.infoconfig.MediatorCommitteeMapper;
import cn.wuxing.mediation.businessplatform.mapper.infoconfig.WindowMapper;
import cn.wuxing.mediation.businessplatform.mapper.system.DeptMapper;
import cn.wuxing.mediation.businessplatform.service.BaseBusinessListService;
import cn.wuxing.mediation.common.core.domain.entity.CmOperatingRecord;
import cn.wuxing.mediation.common.core.domain.model.LoginUser;
import cn.wuxing.mediation.common.utils.DateUtils;
import cn.wuxing.mediation.common.utils.SecurityUtils;
import cn.wuxing.mediation.common.utils.StringUtils;
import cn.wuxing.mediation.common.utils.bean.BeanUtils;
import cn.wuxing.mediation.common.utils.des.DESUtil;
import cn.wuxing.mediation.system.domain.UserTownshipCenter;
import cn.wuxing.mediation.system.mapper.UserTownshipCenterMapper;
import cn.wuxing.mediation.system.util.Desensitization;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @description: 业务列表查询
 * @author:
 * @date 2023-09-07 9:59
 * @version: 1.0 <br>
 */
@Slf4j
@Service
@SuppressWarnings("all")
public abstract class BaseBusinessListServiceImpl<T extends BaseBusinessListVO, F extends BaseBusinessListDTO> implements
        BaseBusinessListService<T> {

    @Autowired
    private DeptMapper deptMapper;

    @Autowired
    private WindowMapper windowMapper;

    @Autowired
    private MediatorCommitteeMapper mediatorCommitteeMapper;

    @Autowired
    private CmOperatingRecordMapper cmOperatingRecordMapper;

    @Autowired
    private CmOperatingRecordMapper operatingRecordMapper;

    @Autowired
    private UserTownshipCenterMapper userTownshipCenterMapper;

    private static final String SORT_FIELD = "sortDate";

    @Override
    public List<ApplicantHistoryListVO> getApplicantHistoryList(String idCard) {
        if (StringUtils.isBlank(idCard)) {
            return new LinkedList<>();
        }
        if (StringUtils.isNotBlank(idCard)) {
            idCard = DESUtil.encrypt(idCard);
        }
        List<ApplicantHistoryListVO> businessList = BusinessFactory.doInstanceRealization(
                this.getClass().getAnnotation(BusinessTag.class).tag(),
                BaseBusinessListMapper.class).getApplicantHistoryList(idCard);

        if (businessList.isEmpty()) {
            return new LinkedList<>();
        }

        //数据组装
        this.commonHandlerApplicantHistoryList(businessList);

        return businessList;
    }

    @Override
    public List<T> getBusinessList(HttpServletRequest request) {
        //获取入参
        F f = this.doAssemblyParams(BeanUtils.doAssemblyParams(this.getClass(), 1, request));
        log.info("BaseTransferOwnershipService [] getTransferOwnershipPaging f :{}", JSONUtil.toJsonStr(f));

        // 处理入参
        this.handerParams(f);

        startPage();
        //获取分页-
        List<T> businessList = BusinessFactory.doInstanceRealization(
                this.getClass().getAnnotation(BusinessTag.class).tag(),
                BaseBusinessListMapper.class).getBusinessList(f);

        if (businessList.isEmpty()) {
            return new LinkedList<>();
        }

        //数据组装
        this.handlerList(businessList, f);
        return businessList;
    }


    /**
     * 分页数据
     *
     * @param dto
     */
    protected F doAssemblyParams(F dto) {
        // 设置处理人
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (null == loginUser || "1".equals(String.valueOf(loginUser.getUserId()))) {
            return dto;
        }

        if (StringUtils.isBlank(dto.getPageType())) {
            dto.setRegisterUserId(loginUser.getUserId());
            return dto;
        }

        // 查询登录人所在乡镇部门id
        dto.setVillagesSgCenterIds(this.getUserTownshipCenterIds(loginUser));
        // 查询登录人所在窗口id
        dto.setWindowIds(this.windowMapper.getWindowIdByUserId(loginUser.getUserId()));
        // 查询登录人在调解委员会的id
        dto.setMediatorCommitteeUserIds(Arrays.asList(loginUser.getUserId()));
        return dto;
    }

    private List<Long> getUserTownshipCenterIds(LoginUser loginUser) {
        UserTownshipCenter userTownshipCenter = new UserTownshipCenter();
        userTownshipCenter.setUserId(loginUser.getUserId());
        List<UserTownshipCenter> userTownshipCenters = this.userTownshipCenterMapper.selectUserTownshipCenterList(
                userTownshipCenter);

        if (CollUtil.isEmpty(userTownshipCenters)) {
            return null;
        }

        return userTownshipCenters.stream().map(UserTownshipCenter::getTownshipId).collect(Collectors.toList());

    }

    /**
     * 分页数据
     *
     * @param records
     * @param f
     */
    void handlerList(List<T> records, F f) {
        if (CollUtil.isEmpty(records)) {
            return;
        }
        records.stream().forEach(item -> // 解密 脱敏
                item.setApplicantName(
                        Desensitization.custNameDesensitization(this.decryptApplicantName(item.getApplicantName()))));
        this.handlerList(records);
    }

    void commonHandlerApplicantHistoryList(List<ApplicantHistoryListVO> records) {
        if (CollUtil.isEmpty(records)) {
            return;
        }

        List<String> eventIds = records.stream().map(ApplicantHistoryListVO::getId).collect(Collectors.toList());

        HanderTypeRecordVO handerTypeRecord = getHanderTypeRecord(eventIds);
        Map<Long, List<CmOperatingRecord>> acceptRecordMap = handerTypeRecord.getAcceptRecordMap();
        Map<Long, List<CmOperatingRecord>> mediateRecordMap = handerTypeRecord.getMediateRecordMap();

        records.forEach(item -> {
            if (null != acceptRecordMap) {
                List<CmOperatingRecord> acceptRecordList = acceptRecordMap.get(Long.valueOf(item.getId()));
                acceptRecordList.stream()
                        .sorted(Comparator.comparing(CmOperatingRecord::getCreateTime).reversed()).findAny()
                        .ifPresent(cmOperatingRecord -> item.setAcceptUser(cmOperatingRecord.getOperatingUserName()));

            }
            if (null != mediateRecordMap) {
                List<CmOperatingRecord> mediateRecordsList = mediateRecordMap.get(Long.valueOf(item.getId()));
                mediateRecordsList.stream()
                        .sorted(Comparator.comparing(CmOperatingRecord::getCreateTime).reversed()).findAny()
                        .ifPresent(mediateRecord -> item.setMediateUser(mediateRecord.getOperatingUserName()));
            }
            // 解密
            item.setApplicantName(this.decryptApplicantName(item.getApplicantName()));
        });
    }

    /**
     * 解密
     *
     * @param applicantName
     * @return
     */
    private String decryptApplicantName(String applicantName) {
        log.info("BaseBusinessListServiceImpl [] decryptApplicantName applicantName :{}", applicantName);
        if (StringUtils.isBlank(applicantName)) {
            return null;
        }
        List<String> names = StringUtils.str2List(applicantName, ",", true, true);
        List<String> result = new ArrayList<>(names.size());
        names.stream().forEach(name -> result.add(DESUtil.decrypt(name)));
        return StringUtils.getStringByList(result, ",");
    }


    abstract void handlerList(List<T> records);
    abstract void handerParam(F dto);

    public void handerParams(F dto) {
        if (StringUtils.isNotBlank(dto.getApplicantUser())) {
            dto.setApplicantUser(DESUtil.encrypt(dto.getApplicantUser()));
        }
        if (StringUtils.isNotBlank(dto.getStartRegistrationTime())) {
            dto.setStartRegistrationTime(DateUtil.format(
                    DateUtils.getStartOfDay(DateTime.of(dto.getStartRegistrationTime(), "yyyy-MM-dd HH:mm:ss")),
                    "yyyy-MM-dd HH:mm:ss"));
        }
        if (StringUtils.isNotBlank(dto.getEndRegistrationTime())) {
            dto.setEndRegistrationTime(DateUtil.format(
                    DateUtils.getEndOfDay(DateTime.of(dto.getEndRegistrationTime(), "yyyy-MM-dd HH:mm:ss")),
                    "yyyy-MM-dd HH:mm:ss"));
        }
        if (null == dto.getDraftFlag()) {
            dto.setDraftFlag(0);
        }
        if (StringUtils.isNotBlank(dto.getIds())) {
            dto.setIdList(Convert.toList(String.class, dto.getIds()));
        }

        this.handerParam(dto);

    }

    protected HanderTypeRecordVO getHanderTypeRecord(List<String> eventIds) {
        HanderTypeRecordVO handerTypeRecordVO = new HanderTypeRecordVO();

        List<CmOperatingRecord> cmOperatingRecords = this.cmOperatingRecordMapper.selectList(
                Wrappers.<CmOperatingRecord>lambdaQuery()
                        .select(CmOperatingRecord::getId, CmOperatingRecord::getOperatingUserName,
                                CmOperatingRecord::getCreateTime)
                        .in(CmOperatingRecord::getId, eventIds)
                        .eq(CmOperatingRecord::getOperatingType, OperatingTypeEnum.getHanderType()));

        if (CollUtil.isEmpty(cmOperatingRecords)) {
            return handerTypeRecordVO;
        }

        // 专窗 受理记录
        List<CmOperatingRecord> acceptRecords = cmOperatingRecords.stream()
                .filter(i -> OperatingTypeEnum.ACCEPT.getCode().equals(i.getOperatingType())).collect(
                        Collectors.toList());

        if (CollUtil.isNotEmpty(acceptRecords)) {
            // 专窗 受理记录map
            Map<Long, List<CmOperatingRecord>> acceptRecordMap = acceptRecords.stream().collect(
                    Collectors.groupingBy(CmOperatingRecord::getId));
            handerTypeRecordVO.setAcceptRecordMap(acceptRecordMap);
        }

        // 调解 受理记录
        List<CmOperatingRecord> mediateRecords = cmOperatingRecords.stream()
                .filter(i -> OperatingTypeEnum.MEDIATE.getCode().equals(i.getOperatingType())).collect(
                        Collectors.toList());

        if (CollUtil.isNotEmpty(mediateRecords)) {
            // 调解 受理记录map
            Map<Long, List<CmOperatingRecord>> mediateRecordMap = mediateRecords.stream().collect(
                    Collectors.groupingBy(CmOperatingRecord::getId));
            handerTypeRecordVO.setMediateRecordMap(mediateRecordMap);
        }
        return handerTypeRecordVO;
    }

    public ChangeWindowDetailVO getChangeWindowDetail(Long eventId, Integer eventCategory) {
        ChangeWindowDetailVO changeWindowDetailVO = new ChangeWindowDetailVO();
        CmOperatingRecord cmOperatingRecord = this.cmOperatingRecordMapper.selectOne(
                Wrappers.<CmOperatingRecord>lambdaQuery()
                        .eq(CmOperatingRecord::getEventId, eventId)
                        .eq(CmOperatingRecord::getOperatingType, OperatingTypeEnum.CHANG_WINDOW.getCode())
                        .eq(CmOperatingRecord::getEventCategory, eventCategory)
                        .isNotNull(CmOperatingRecord::getChangeWindowId)
                        .orderByDesc(CmOperatingRecord::getOperatingTime).last("limit 1"));

        BeanUtils.copyProperties(cmOperatingRecord, changeWindowDetailVO);
        return changeWindowDetailVO;
    }
}
